package net.sf.midollo.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;

public class IOStreamConnector implements Runnable {

  protected final InputStream is;
  protected final OutputStream os;
  protected byte[] buffer;
  protected IOException error;

  public IOStreamConnector(IOStream ioStream, int bufSize) throws IOException {
    this(ioStream.getInput(), ioStream.getOutput(), bufSize);
  }

  public IOStreamConnector(InputStream is, OutputStream os, int bufSize) {
    this.is = is;
    this.os = os;
    this.buffer = new byte[bufSize];
  }

  public InputStream getInput() {
    return this.is;
  }

  public OutputStream getOutput() {
    return this.os;
  }

  public IOException getError() {
    return this.error;
  }

  public void runConnector() throws IOException {
    // final String id = Integer.toHexString(System.identityHashCode(this));
    int nread, available;
    while (true) {
      try {
        available = this.is.available();
        available = available <= 0 ? 1 : (available > this.buffer.length ? this.buffer.length : available);
        // Utils.log("IOSC" + id + " R" + available);
        nread = this.is.read(this.buffer, 0, available);
      } catch (InterruptedIOException e) {
        nread = e.bytesTransferred;
      }
      if (nread < 0) {
        this.os.flush();
        break;
      }
      // Utils.log("IOSC" + id + " W" + nread);
      this.os.write(this.buffer, 0, nread);
      this.os.flush();
    }
    // Utils.log("IOSC" + id + " end");
  }

  public void run() {
    try {
      this.error = null;
      runConnector();
    } catch (IOException e) {
      this.error = e;
    }
  }
}
